﻿#region Imports
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using CommonUtilities.Attributes;
using CommonUtilities.Commands;
using CommonUtilities.Enums;
using CommonUtilities.Extensions;
using CommonUtilities.Messages;
using CommonUtilities.Util;
using SeriesEpisodeMapper.Models;
#endregion Imports

namespace SeriesEpisodeMapper.ViewModels
{
    public class MainViewModel : BaseViewModel
    {
        ObservableCollection<string> sAllData;
        ObservableCollection<EpisodeInfo> ForConv = new ObservableCollection<EpisodeInfo>();
        private int SeasonPadLength = 2;
        private int EpisodePadLength = 2;
        internal const string sNA = "--";
        internal const string sDefaultAll = "_All";
        ObservableCollection<string> allFiles;
        public string DataDelimeter { get; set; }
        public string FieldDelimeter { get; set; }
        enum eSeriesPathMode { Single, FromMap }
        private eSeriesPathMode Current { get; set; }

        #region Command declarations
        public ICommand BrowseSourceCommand { get; private set; }
        public ICommand BrowseSeriesPathCommand { get; private set; }
        public ICommand SelectedSeriesCommand { get; private set; }
        public ICommand SelectTargetCommand { get; private set; }
        public ICommand SaveMapCommand { get; private set; }
        public ICommand ClearMapCommand { get; private set; }
        public ICommand LoadFileCommand { get; private set; }
        public ICommand GenerateFileNameCommand { get; private set; }
        public ICommand LinkFileCommand { get; private set; }
        public ICommand RenameFileCommand { get; private set; }
        public ICommand RevertBackCommand { get; set; }
        public ICommand QuitAppCommand { get; set; }
        #endregion Command declarations

        #region Properties
        private ObservableCollection<FieldMap> mapFields = new ObservableCollection<FieldMap>();
        public ObservableCollection<FieldMap> MapFields
        {
            get { return mapFields; }
            set { mapFields = value; RaisePropertyChanged("MapFields"); }
        }

        public ObservableCollection<FieldMap> MapFieldsSaved { get; set; }

        private ObservableCollection<string> sourceFields = new ObservableCollection<string>();
        public ObservableCollection<string> SourceFields
        {
            get { return sourceFields; }
            set { sourceFields = value; RaisePropertyChanged("SourceFields"); }
        }

        private FInfo sourceFileInfo;
        public FInfo SourceFileInfo
        {
            get { return sourceFileInfo; }
            set
            {
                IsDirty = !sourceFileInfo.IsNull() && sourceFileInfo.FilePath != value.FilePath;
                sourceFileInfo = value; RaisePropertyChanged("SourceFileInfo");
            }
        }

        private FInfo seriesPathFileInfo;
        public FInfo SeriesPathFileInfo
        {
            get { return seriesPathFileInfo; }
            set
            {
                //IsDirty = !seriesPathFileInfo.IsNull() && seriesPathFileInfo.FilePath != value.FilePath; RKD
                seriesPathFileInfo = value; RaisePropertyChanged("SeriesPathFileInfo");
            }
        }

        private string targetDirectory;
        public string TargetDirectory
        {
            get { return targetDirectory; }
            set { targetDirectory = value; RaisePropertyChanged("TargetDirectory"); }
        }

        private bool isMapLoaded;
        public bool IsMapLoaded
        {
            get { return isMapLoaded; }
            set { isMapLoaded = value; RaisePropertyChanged("IsMapLoaded"); }
        }

        private ObservableCollection<EpisodeInfo> allEpisodesRAW = new ObservableCollection<EpisodeInfo>();
        public ObservableCollection<EpisodeInfo> AllEpisodesRAW
        {
            get { return allEpisodesRAW; }
            set { allEpisodesRAW = value; RaisePropertyChanged("AllEpisodesRAW"); }
        }

        private ObservableCollection<SeriesInfo> allSeriesPathRAW = new ObservableCollection<SeriesInfo>();
        public ObservableCollection<SeriesInfo> AllSeriesPathRAW
        {
            get { return allSeriesPathRAW; }
            set { allSeriesPathRAW = value; RaisePropertyChanged("AllSeriesPathRAW"); }
        }

        private ObservableCollection<EpisodeInfo> allEpisodes = new ObservableCollection<EpisodeInfo>();
        public ObservableCollection<EpisodeInfo> AllEpisodes
        {
            get { return allEpisodes; }
            set { allEpisodes = value; RaisePropertyChanged("AllEpisodes"); }
        }

        private ObservableCollection<SeriesInfo> allSeries = new ObservableCollection<SeriesInfo>();
        public ObservableCollection<SeriesInfo> AllSeries
        {
            get { return allSeries; }
            set { allSeries = value; RaisePropertyChanged("AllSeries"); }
        }

        private bool isSingleSeries;
        public bool IsSingleSeries
        {
            get { return isSingleSeries; }
            set
            {
                isSingleSeries = value; RaisePropertyChanged("IsSingleSeries");

                SelectedSeries = AllSeries._Where(srs => srs.SeriesTitle == sDefaultAll).FirstOrDefault();
                // RefreshEpisodeList();
            }
        }

        private SeriesInfo selectedSeries;
        public SeriesInfo SelectedSeries
        {
            get { return selectedSeries; }
            set
            {
                if (selectedSeries == value) return;
                else
                {
                    selectedSeries = value; RaisePropertyChanged("SelectedSeries");
                    SelectedSeriesCommand.Execute(null);
                }
            }
        }

        private bool isDirty;
        public bool IsDirty
        {
            get { return isDirty; }
            set
            {
                isDirty = value;
                if (isDirty || lastDirtyChanged == DateTime.MinValue) lastDirtyChanged = DateTime.Now; ;
            }
        }

        private DateTime lastDirtyChanged;
        public DateTime LastDirtyChanged { get { return lastDirtyChanged; } }

        private DateTime lastFileUpdateOn;
        public DateTime LastFileUpdateOn { get { return lastFileUpdateOn; } }

        public DelimeterSelectorViewModel DelimeterSettings { get; set; }
        #endregion Properties

        #region Constructors
        public MainViewModel()
        {
            DelimeterSettings = new DelimeterSelectorViewModel();

            InitCommands();
            AddMappingFields();

            if (Debugger.IsAttached)
            {
                BrowseSourceCommand.Execute(null);
                BrowseSeriesPathCommand.Execute(null);
                DelimeterSettings.SelectedDataDelimeter = DelimeterSettings.AllDataDelimeter.Last();
                DelimeterSettings.SaveDelimeterCommand.Execute(null);
                DelimeterSettings.LoadSourceCommand.Execute(null);
                //SaveMapCommand.Execute(null);
            }
        }
        #endregion Constructors

        #region Methods
        private void InitCommands()
        {
            BrowseSourceCommand = new RelayCommand<object>((parameter) => { BrowseSource(); }, this);
            BrowseSeriesPathCommand = new RelayCommand<object>((parameter) => { BrowseSeriesPath(); }, this);
            SelectedSeriesCommand = new RelayCommand<SeriesInfo>((parameter) => { RefreshEpisodeList(); }, this);
            SelectTargetCommand = new RelayCommand<object>((parameter) => { SelectTarget(); }, this);
            SaveMapCommand = new RelayCommand<object>((parameter) => { SaveMap(); }, this);
            ClearMapCommand = new RelayCommand<object>((parameter) => { ClearMap(); }, this);
            LoadFileCommand = new RelayCommand<object>((parameter) => { LoadFile(); }, this);
            DelimeterSettings.SaveDelimeterCommand = new RelayCommand<object>((parameter) => { SaveDelimeter(); }, this);
            DelimeterSettings.LoadSourceCommand = new RelayCommand<object>((parameter) => { LoadSource(); }, this);
            GenerateFileNameCommand = new RelayCommand<object>((parameter) => { GenerateFileName(); }, this);
            LinkFileCommand = new RelayCommand<object>((parameter) => { LinkFile(); }, this);
            RenameFileCommand = new RelayCommand<object>((parameter) => { RenameFile(); }, this);
            RevertBackCommand = new RelayCommand<object>((parameter) => { RevertFileName(); }, this);
            QuitAppCommand = new RelayCommand<object>((parameter) => { QuitApp(); });
        }

        private void AddMappingFields()
        {
            ObservableCollection<FieldMap> mapFields = new ObservableCollection<FieldMap>();
            AttributeLists<EpisodeInfo>.PropertyMapDataImportNameSafe
                ._OrderBy(map =>
                {
                    try { return AttributeLists<EpisodeInfo>.PropertyMapSortIndex[map.Key]; }
                    catch (Exception) { return 999; }
                })
                ._ForEach(map =>
                {
                    if (AttributeLists<EpisodeInfo>.PropertyFieldsBrowsable.Contains(map.Key))
                        mapFields.Add(new FieldMap { TargetProperty = map.Key, TargetPropertyDisplay = map.Value, /*SourceFields = this.SourceFields/*.Select(kvp => kvp.Key)*/ });
                });

            MapFields = mapFields;
        }

        private void BrowseSource()
        {
            if (Debugger.IsAttached && SourceFileInfo.IsNull())
                sourceFileInfo = new FInfo { FilePath = @"Y:\_series\TV_series_full.txt" };

            string initialDirectory = Directory.Exists((SourceFileInfo.IsNull() ? new FInfo() : SourceFileInfo).FileFolder)
                   ? SourceFileInfo.FileFolder : Environment.SpecialFolder.MyDocuments.GetFolderPath();
            string fileName = (SourceFileInfo.IsNull() ? new FInfo() : SourceFileInfo).FilePath;

            var dlg = DialogInitializers.Create_OpenFileDialog(title: "Open file to read episode info from..",
                 defaultExt: "txt", filter: "Text files (*.txt)|*.txt",
                 initialDirectory: initialDirectory, fileName: fileName);

            if (dlg.ShowDialog() == DialogResult.OK)
                SourceFileInfo = new FInfo { FilePath = dlg.FileName };
        }

        private void BrowseSeriesPath()
        {
            if (Debugger.IsAttached && SeriesPathFileInfo.IsNull())
                SeriesPathFileInfo = new FInfo { FilePath = @"Y:\_series\TV_series_path.txt" };

            string initialDirectory = Directory.Exists((SeriesPathFileInfo.IsNull() ? new FInfo() : SeriesPathFileInfo).FileFolder)
                    ? SeriesPathFileInfo.FileFolder : Environment.SpecialFolder.MyDocuments.GetFolderPath();
            string fileName = (SeriesPathFileInfo.IsNull() ? new FInfo() : SeriesPathFileInfo).FilePath;

            var dlg = DialogInitializers.Create_OpenFileDialog(title: "Open file to read series-path map from..",
                defaultExt: "txt", filter: "Text files (*.txt)|*.txt",
                initialDirectory: initialDirectory, fileName: fileName);

            if (dlg.ShowDialog() == DialogResult.OK)
                SeriesPathFileInfo = new FInfo { FilePath = dlg.FileName };
        }

        private void SelectTarget()
        {
            // Ctrl+Click to load path manually
            if (Form.ModifierKeys == Keys.Control)
            {
                string clipText = String.Empty;
                if (Clipboard.ContainsText()) clipText = Clipboard.GetText();
                targetDirectory = Directory.Exists(clipText) ? Clipboard.GetText() : String.Empty;
                if (Debugger.IsAttached && !Directory.Exists(targetDirectory)) targetDirectory = @"Y:\_series\DOWN\Louie";

                var dlg = DialogInitializers.Create_FolderBrowserDialog(desc: "Select target directory..",
                    path: TargetDirectory.Coalesce(Environment.SpecialFolder.MyDocuments.GetFolderPath()), root: Environment.SpecialFolder.Desktop);

                if (dlg.ShowDialog() == DialogResult.OK)
                    TargetDirectory = dlg.SelectedPath;

                Current = eSeriesPathMode.Single;
            }
            else
            {
                AllEpisodesRAW._ForEach(ep =>
                    ep.SeriesPath = AllSeriesPathRAW._Where(srs => srs.SeriesTitle == ep.SeriesTitle)
                        .FirstOrDefault().Coalesce(new SeriesInfo()).SeriesPath);

                Current = eSeriesPathMode.FromMap;
            }
        }

        private void LoadSource()
        {
            if (!ValidateDelimters()) return;

            sAllData = File.ReadAllLines(SourceFileInfo.FilePath).ToObservableCollection();
            SourceFields = sAllData.First().Split(DataDelimeter.ToCharArray()).ToObservableCollection()._Select(col => col).ToObservableCollection();

            IsMapLoaded = SourceFields.Count > 0;
            MapFields._ForEach(map => map.SelectedSourceField = map.TargetPropertyDisplay); // Map automatically, if matches
        }

        private void SaveMap()
        {
            if (!ValidateDelimters()) return;

            if (ValidateMap())
            {
                MapFieldsSaved = Serializer.DeSerializeFromFormattedData<ObservableCollection<FieldMap>>(
                    Serializer.SerializeToFormattedData(MapFields, eSerializationFormat.JSon), eSerializationFormat.JSon);

                LoadFile();
            }
            else MessageBoxUtil.Show(Debugger.IsAttached, "Map all fields before saving..");
        }

        private bool ValidateMap()
        {
            return MapFields._Where(map => String.IsNullOrEmpty(map.SelectedSourceField))._None();
        }

        private void ClearMap()
        {
            MapFieldsSaved = new ObservableCollection<FieldMap>();
            MapFields._ForEach(map => map.SelectedSourceField = null);

            DelimeterSettings.SelectedFieldDelimeter = DelimeterSettings.SelectedDataDelimeter = null;
            AllSeries = new ObservableCollection<SeriesInfo>();
            AllEpisodesRAW = AllEpisodes = new ObservableCollection<EpisodeInfo>();
        }

        private bool ValidateDelimters()
        {
            string msg = " not set!\nPlease save to proceed..";
            if (DataDelimeter.IsNullOrEmpty() && FieldDelimeter.IsNullOrEmpty()) { MessageBoxUtil.Show(Debugger.IsAttached, "Data/Field delimeter are" + msg); return false; }
            else if (DataDelimeter.IsNullOrEmpty()) { MessageBoxUtil.Show(Debugger.IsAttached, "Data delimeter is " + msg); return false; }
            else if (FieldDelimeter.IsNullOrEmpty()) { MessageBoxUtil.Show(Debugger.IsAttached, "Field delimeter is " + msg); return false; }

            return true;
        }

        private void LoadFile()
        {
            if (!ValidateDelimters()) return;

            var seriesName = SourceFields.IndexOf(MapFieldsSaved._Where(map => map.TargetProperty == "SeriesTitle").FirstOrDefault().SelectedSourceField);
            var seasonIndex = SourceFields.IndexOf(MapFieldsSaved._Where(map => map.TargetProperty == "SeasonIndex").FirstOrDefault().SelectedSourceField);
            var episodeIndex = SourceFields.IndexOf(MapFieldsSaved._Where(map => map.TargetProperty == "EpisodeIndex").FirstOrDefault().SelectedSourceField);
            var title = SourceFields.IndexOf(MapFieldsSaved._Where(map => map.TargetProperty == "EpisodeTitle").FirstOrDefault().SelectedSourceField);

            // Read episode info
            AllEpisodesRAW = new ObservableCollection<EpisodeInfo>();
            AllEpisodesRAW = sAllData._Where(data => data != sAllData.First())._Select(row =>
                {
                    var rowData = row.Split(DataDelimeter.ToCharArray());

                    int season; int episode;
                    Int32.TryParse(rowData[seasonIndex], out season);
                    Int32.TryParse(rowData[episodeIndex], out episode);
                    var series = rowData[seriesName].Trim(FieldDelimeter.ToCharArray());
                    var epTitle = rowData[title].Trim(FieldDelimeter.ToCharArray()).Replace(": Part", "-part").Replace("/", " - ");

                    return new EpisodeInfo
                    {
                        SeriesTitle = series,
                        SeriesPath = AllSeriesPathRAW._Where(srs => srs.SeriesTitle == series)
                            ._Select(srs => srs.SeriesPath).FirstOrDefault(),

                        SeasonIndex = season,
                        EpisodeIndex = episode,
                        EpisodeTitle = epTitle,

                        SEIndex = "",
                        FileNameFormatted = "",
                        IsConverted = false,
                        BackColour = Brushes.Transparent,
                    };
                }).ToObservableCollection();

            var allSeasons = AllEpisodesRAW._Select(ssn => ssn.SeriesTitle).Distinct();
            AllEpisodesRAW._ForEach(ep => ep.SeriesBackColour = allSeasons.ToList().IndexOf(ep.SeriesTitle) % 2 == 0 ? Brushes.LightBlue : Brushes.LightGreen);

            // Read from series-path map
            var sAllData2 = File.ReadAllLines(SeriesPathFileInfo.FilePath).ToObservableCollection();
            var sHeader = sAllData2.First().Split(DataDelimeter.ToCharArray()).ToObservableCollection()._Select(col => col).ToObservableCollection();
            AllSeriesPathRAW = sAllData2._Where(data => data != sAllData2.First())._Select(data =>
            {
                var z = data.Split('\t');
                return new SeriesInfo
                {
                    SeriesTitle = z.FirstOrDefault(),
                    SeriesPath = z.LastOrDefault()
                };
            }).ToObservableCollection();

            if (lastFileUpdateOn == DateTime.MinValue || (IsDirty && LastFileUpdateOn < LastDirtyChanged))
            {
                AllSeries = AllEpisodesRAW._Select(ep => ep.SeriesTitle.Trim('"')).Distinct()._OrderBy()
                   ._Select(srs => new SeriesInfo { SeriesTitle = srs }).ToObservableCollection();

                AllSeries.Insert(0, new SeriesInfo { SeriesTitle = sDefaultAll });
                SelectedSeries = AllSeries._Where(srs => srs.SeriesTitle == sDefaultAll).FirstOrDefault();

                lastFileUpdateOn = DateTime.Now;
            }
            else // (default trgigger; but in ELSE as 'SelectedSeries' will automatically trigger
                SelectedSeriesCommand.Execute(null); ; // RefreshEpisodeList();
        }

        /// <summary>
        /// Refreshes episode list against selected series or displays all
        /// <para/>(DO NOT CALL DIRECTLY) Call via SelectedSeriesCommand.Execute(null)
        /// </summary>
        private void RefreshEpisodeList()
        {
            if (IsSingleSeries && !SelectedSeries.IsNull())
            {
                AllEpisodes = ((SelectedSeries.SeriesTitle == sDefaultAll) ? AllEpisodesRAW
                    : AllEpisodesRAW._Where(ep => ep.SeriesTitle == SelectedSeries.SeriesTitle)).ToObservableCollection();
                AllEpisodes._ForEach(ep =>
                    {
                        ep.SEIndex = "";
                        ep.FileNameFormatted = "";
                        ep.IsConverted = false;
                        ep.BackColour = Brushes.Transparent;
                        ep.SeriesBackColour = Brushes.Transparent;
                    });
            }
            else
            {
                //if (!IsSingleSeries) SelectedSeries = null; RKD
                AllEpisodes = AllEpisodesRAW.ToObservableCollection();
            }
        }

        private void SaveDelimeter()
        {
            if (DelimeterSettings.SelectedDataDelimeter != null && DelimeterSettings.SelectedFieldDelimeter != null)
            {
                DataDelimeter = DelimeterSettings.SelectedDataDelimeter.Delimeter;
                FieldDelimeter = DelimeterSettings.SelectedFieldDelimeter.Delimeter;
            }
            else
            {
                var msg = String.Format("Please save delimeters: {0}{1}",
                    DelimeterSettings.SelectedDataDelimeter == null ? "\n   * Data" : String.Empty,
                    DelimeterSettings.SelectedFieldDelimeter == null ? "\n   * Field" : String.Empty);
                MessageBox.Show(msg, "Warning..", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void GenerateFileName()
        {
            AllEpisodes._ForEach(ep =>
            {
                ep.SEIndex = "s{0}e{1}".FormatTextFromParams(ep.SeasonIndex.PadLeft(SeasonPadLength, '0'), ep.EpisodeIndex.PadLeft(EpisodePadLength, '0'));
                ep.FileNameFormatted = "{0} - {1}".FormatTextFromParams(ep.SEIndex, ep.EpisodeTitle.Replace(": ", " - "));
            });
        }

        private void LinkFile(bool refresh = false)
        {
            int indexLength = "se".Length + SeasonPadLength + EpisodePadLength;

            if (Current == eSeriesPathMode.Single && Directory.Exists(TargetDirectory))
                allFiles = Directory.GetFiles(TargetDirectory, "*.*", SearchOption.AllDirectories).ToObservableCollection();
            else
            {
                allFiles = new ObservableCollection<string>();
                AllSeriesPathRAW._Select(srs => srs.SeriesPath).Distinct()
                    ._ForEach(path => { if (Directory.Exists(path)) allFiles = allFiles.AddItems(Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)).ToObservableCollection(); });
            }

            AllEpisodes._ForEach(ep =>
                {
                    var filesToEdit = allFiles._Where(path => Path.GetFileNameWithoutExtension(path) == ep.FileNameFormatted || Path.GetFileNameWithoutExtension(path) == ep.SEIndex);
                    if (filesToEdit._Select(path => Path.GetFileNameWithoutExtension(path)).Distinct().Count() > 1) ep.IsConverted = null;
                    else ep.IsConverted = filesToEdit._Where(path => Path.GetFileNameWithoutExtension(path) == ep.SEIndex)._None();

                    if (ep.IsConverted.HasValue) ep.BackColour = ep.IsConverted.Value ? Brushes.Green : Brushes.Red;
                    else ep.BackColour = Brushes.Yellow;

                    var c = filesToEdit._Select(path => Path.GetFileNameWithoutExtension(path)).Distinct();
                    if (ValidateForRename(ep)) LinkFile(ep, filesToEdit);
                    else ep.ParentFolder = sNA;

                    if (ForConv._Select(conv => conv.FileNameFormatted)._Contains(ep.FileNameFormatted))
                        ep.BackColour = Brushes.LightGreen;

                    if (ep.BackColour == Brushes.Green) ep.InfoTip = "fully renamed";
                    if (ep.BackColour == Brushes.Red) ep.InfoTip = "not renamed";
                    if (ep.BackColour == Brushes.Yellow) ep.InfoTip = "party renamed";
                    if (ep.BackColour == Brushes.LightGreen) ep.InfoTip = "just changed..";
                });

            if (refresh)
            {
                ForConv = new ObservableCollection<EpisodeInfo>();
                if (MessageBoxUtil.Show(Debugger.IsAttached, "Refresh file list to link?", "Confirmation..", MessageBoxButtons.YesNo) == DialogResult.Yes) LinkFile();
            }
        }

        private bool ValidateForRename(EpisodeInfo ep)
        {
            if (ep.IsConverted.HasValue) return !ep.IsConverted.Value;
            else return true;
        }

        private void LinkFile(EpisodeInfo ep, IEnumerable<string> filesToEdit)
        {
            if (filesToEdit._Any())
            {
                ep.ParentFolder = Path.GetDirectoryName(filesToEdit.First()).Replace(TargetDirectory, "~");
                ep.AllExtns = filesToEdit._Where(path => Path.GetFileNameWithoutExtension(path) == ep.SEIndex)
                    ._Select(path => Path.GetExtension(path)).ToObservableCollection();
            }
        }

        private void RenameFile()
        {
            string log = ""; bool abort = false;
            DateTime startTime = DateTime.Now;

            AllEpisodes._Where(ep => ValidateForRename(ep))._ForEach(ep =>
            {
                if (!abort) log += RenameFile(ep, ref abort);  // Partly / None converted
            });

            if (!log.IsNullOrEmpty())
            {
                string logPath = SourceFileInfo.FileFolder.AppendPath("conversion.log");

                File.AppendAllText(logPath, "********************** START {0} **********************{1}".FormatTextFromParams(startTime.ToString("yyyy-MM-dd HH:mm:ss"), Environment.NewLine));
                File.AppendAllText(logPath, log); // Write log
                File.AppendAllText(logPath, "********************** END {0} **********************{1}".FormatTextFromParams(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Environment.NewLine.Repeator(2)));

                Process.Start("notepad", logPath);
            }

            LinkFile(true);
        }

        private string RenameFile(EpisodeInfo ep, ref bool abort)
        {
            string log = "";
            bool _abort = abort;

            if (!_abort)
            {
                var dir = ep.ParentFolder.Replace("~", TargetDirectory);
                var src = Path.Combine(dir, ep.SEIndex);
                var tgt = Path.Combine(dir, ep.FileNameFormatted);

                try
                {
                    ep.AllExtns._ForEach(ext =>
                        {
                            if (MessageBoxUtil.Show(false, ep.FileNameFormatted + " :: " + ext.ToUpper(), "Proceed?", MessageBoxButtons.YesNo) != DialogResult.Yes)
                                _abort = true;

                            if (!_abort)
                            {
                                ForConv.Add(ep);

                                File.Move(src + ext, tgt + ext);
                                log += "{0}\t{1}\t{2}{3}".FormatTextFromParams(ext, src, tgt, Environment.NewLine);
                            }
                        });
                }
                catch (Exception ex) { }
                finally { ep.IsConverted = File.Exists(tgt); }
            }

            abort = _abort;
            return log;
        }

        private void RevertFileName()
        {
            AllEpisodes._ForEach(ep =>
            {
                ForConv.Add(ep);
                allFiles._Where(fl => Path.GetFileNameWithoutExtension(fl) == ep.FileNameFormatted)
                    ._ForEach(fl => File.Move(fl, fl.GetDirectoryNameFull().AppendPath(ep.SEIndex + Path.GetExtension(fl))));
            });

            LinkFile(true);
        }

        private void QuitApp()
        {
            if (MessageBoxUtil.Show(Debugger.IsAttached, "Do you really want to exit?", "Exiting..", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                System.Windows.Application.Current.Shutdown();
        }
        #endregion Methods
    }
}
